{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Mf0pK2uGkw5h"
   },
   "source": [
    "# Chapter 5 - Control flows and Iterables：流程控制與疊代"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "EL3d0Z2uCauf"
   },
   "source": [
    "## `range()`：建立範圍序列物件"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "oZGpw-EfUOSf"
   },
   "source": [
    "在談到流程控制以前，我們會先介紹一個很實用的物件：範圍 (Range)。\n",
    "\n",
    "> 備註：為了中文教學需要，我硬是翻譯了一下，所以定名為「範圍」。但實際上，官方似乎沒有對這個物件定下官方譯名，未來如果有溝通的困難，請各位還是稱其為 Range 物件。\n",
    "\n",
    "與 List 相似，範圍物件也是一種序列 (Sequence) 物件，用來產生一組數列，而我們可以透過設定參數，去指定序列的起始數字、結尾數字 - 1、以及每個數字之間的差值。\n",
    "\n",
    "> 備註：沒錯，這三個參數就是 `start`, `stop`, 與 `step`。是不是跟字串和串列的索引十分相似？\n",
    "\n",
    "References:\n",
    "\n",
    "* [class range - Python Documentation](https://docs.python.org/3/library/functions.html#func-range)\n",
    "* [Ranges - Python Documentation](https://docs.python.org/3/library/stdtypes.html#ranges)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 1482,
     "status": "ok",
     "timestamp": 1606972748055,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "ElGT4snQCf-r",
    "outputId": "928b2c4d-be3d-45bf-bcd2-45fc94ca676d"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "range(0, 10)\n"
     ]
    }
   ],
   "source": [
    "print(range(10))  # 嘗試顯示一個串列"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "YmgIlbXKU4wK"
   },
   "source": [
    "直接使用 `print()` 函式來顯示串列內容的話，似乎只會看到設定值。特別的是，如果不指定 `start` 的話，參數將會被指定為 `stop` 的數值。詳情可以參考 `help(range)` 的文件內容。\n",
    "\n",
    "所以要如何才可以顯示串列中的所有數值呢？其中一種方法是用我們先前提到的 `list()` 函式將其轉換為串列："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 722,
     "status": "ok",
     "timestamp": 1606972756037,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "0aQ7OU4BCjUe",
    "outputId": "52d90b7a-a382-4c38-d2b6-ea55e911c738"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n"
     ]
    }
   ],
   "source": [
    "print(list(range(10)))  # 將 range 物件轉換為串列，就可以顯示了"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 689,
     "status": "ok",
     "timestamp": 1606972777202,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "7JnKHaC1ClYi",
    "outputId": "47a502e6-d7f9-4022-8971-11a21ec5b402"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4, 5, 6, 7, 8, 9]\n"
     ]
    }
   ],
   "source": [
    "print(list(range(1,10,1)))  # 試著加上一些設定值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 673,
     "status": "ok",
     "timestamp": 1606972791440,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "VJh5g3ScCqv6",
    "outputId": "6b18a691-1f85-4129-ac8b-2530f84c5b06"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n"
     ]
    }
   ],
   "source": [
    "print(list(range(1,10+1,1)))  # 如果要顯示 1 - 10，應該這樣設定"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 645,
     "status": "ok",
     "timestamp": 1606972804133,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "dkD_PdvfCt39",
    "outputId": "656f3134-034f-4207-aa51-1c27121c83a4"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[10, 8, 6, 4, 2]\n"
     ]
    }
   ],
   "source": [
    "print(list(range(10,0,-2)))  # 也可以產生由大到小的數列"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "L6MbiwaGlIRi"
   },
   "source": [
    "## `if`：流程控制、條件判斷"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "AYAdrhLKmSq_"
   },
   "source": [
    "`if` 陳述式是流程控制的基本元素，在後面接著給定一個成立的條件，並撰寫表達式，就可以讓程式判斷狀態並執行相對應的指令："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 2166,
     "status": "ok",
     "timestamp": 1607586282222,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "BXr6uKflkmkk",
    "outputId": "1aea9f9d-25d9-46d4-f584-a4563b45eb4b"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The name is Vivi\n"
     ]
    }
   ],
   "source": [
    "name = \"Vivi\"  # 建立一個存放名稱字串的物件\n",
    "print(\"The name is\", name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 1983,
     "status": "ok",
     "timestamp": 1607586282233,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "Wx7fcHWllR1c",
    "outputId": "3f5dbc42-eb36-4693-c587-8e0527943419"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Welcome, Vivi!\n"
     ]
    }
   ],
   "source": [
    "if name == \"Vivi\":  # 判斷名稱後作出相應的動作\n",
    "    print(\"Welcome,\", name+\"!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "KCTJsskcldHN"
   },
   "source": [
    "### `else`：設定所有判斷式均不成立時執行的動作"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Sf2nmciSnE-Z"
   },
   "source": [
    "或 `if` 陳述式判斷的條件不成立時，用 `else` 關鍵字來設定此時要執行的動作："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "id": "DCfANjlSl3FP"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The name is Gigi\n"
     ]
    }
   ],
   "source": [
    "name = \"Gigi\"  # 建立一個存放名稱字串的物件\n",
    "print(\"The name is\", name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 744,
     "status": "ok",
     "timestamp": 1606965233997,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "W9ZbM3MKloAL",
    "outputId": "a2a13fe7-5c1a-4e65-9c27-b0c29e691e4e"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Do I know you?\n"
     ]
    }
   ],
   "source": [
    "if name == \"Vivi\":  # 判斷名稱是否等於 'Vivi'\n",
    "    print(\"Welcome,\", name+\"!\")\n",
    "else:               ## 若前項所有條件都不成立時，執行此處的動作\n",
    "    print(\"Do I know you?\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "1w_MtCLfl1KB"
   },
   "source": [
    "### `elif`：設定前一個判斷式不成立時，接著執行的判斷式及動作"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "UQA2xIdgnq7f"
   },
   "source": [
    " 在 `if` 陳述式判斷條件之後，還可以加上 `elif` 來繼續執行多次的判斷："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 641,
     "status": "ok",
     "timestamp": 1606965292958,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "xdx-VA8ll87S",
    "outputId": "d3253564-fee9-412a-bbef-852cac4e1aef"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The name is Kiki\n"
     ]
    }
   ],
   "source": [
    "name = 'Kiki'  # 建立一個存放名稱字串的物件\n",
    "print(\"The name is\", name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 686,
     "status": "ok",
     "timestamp": 1606965360929,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "LuZrPv3FmGzO",
    "outputId": "28ecaa85-0397-4068-a37c-d5866125a715"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Long time no see! Kiki.\n"
     ]
    }
   ],
   "source": [
    "if name == 'Vivi':    # 判斷名稱是否等於 'Vivi'\n",
    "    print(\"Welcome,\", name+\"!\")\n",
    "elif name == 'Kiki':  # 判斷名稱是否等於 'Kiki'\n",
    "    print(\"Long time no see!\", name+\".\")\n",
    "else:                 # 若前項所有條件都不成立時，執行此處的動作\n",
    "    print(\"Do I know you?\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "w__-iBSUsRT7"
   },
   "source": [
    "> 備註：其他程式語言裡通常是寫作 `else if`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Qd10n2WvmU0k"
   },
   "source": [
    "### 經典範例：foo & bar"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "wppKnuLLojDF"
   },
   "source": [
    "記得題目是：驗證一個數字，當她是：\n",
    "\n",
    "* `2` 的倍數：顯示 `Foo`\n",
    "* `3` 的倍數：顯示 `Bar`\n",
    "* `6` 的倍數：顯示 `Foo Bar`\n",
    "* 以上均不成立時，回傳該數字"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 686,
     "status": "ok",
     "timestamp": 1606966956979,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "XInrcJqJqr0q",
    "outputId": "57bc701d-187d-4535-cce4-b2cf174a9dac"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Foo Bar\n"
     ]
    }
   ],
   "source": [
    "n = 12\n",
    "\n",
    "if n % 3 == 0 and n % 2 == 0:\n",
    "    print(\"Foo Bar\")\n",
    "elif not(n % 2):\n",
    "    print(\"Foo\")\n",
    "elif not(n % 3):\n",
    "    print(\"Bar\")\n",
    "else:\n",
    "    print(n)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "c-5kbJW2sgCi"
   },
   "source": [
    "## 疊代、迴圈"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "MGh_uGgMp__w"
   },
   "source": [
    "維基百科對「疊代」的解釋：\n",
    "\n",
    "> 疊代是重複回饋過程的活動，其目的通常是為了接近併到達所需的目標或結果。每一次對過程的重複被稱為一次「疊代」，而每一次疊代得到的結果會被用來作為下一次疊代的初始值。\n",
    "\n",
    "而「迴圈」的部分則是：\n",
    "\n",
    "> 迴圈是計算機科學運算領域的用語，也是一種常見的控制流程。迴圈是一段在程式中只出現一次，但可能會連續執行多次的程式碼。迴圈中的程式碼會執行特定的次數，或者是執行到特定條件成立時結束迴圈，或者是針對某一集合中的所有項目都執行一次。\n",
    "\n",
    "所以這兩個名詞，講的都是我們接下來要做的事情：讓程式重複地進行某個動作。\n",
    "\n",
    "References:\n",
    "\n",
    "* [請問到底是在「疊代」或是在「迭代」？ - Medium](https://ryo6.medium.com/請問到底是在-疊代-或是在-迭代-f5bdba4c31eb)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "a9yh5Z15vT5g"
   },
   "source": [
    "### `for`：For 迴圈 (For loop)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "4qkRXugDs-z2"
   },
   "source": [
    "透過 `for` 陳述句以及 `in` 運算子，可以對序列物件裡的各個物件依序進行處理："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 1271,
     "status": "ok",
     "timestamp": 1607588729594,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "eIwa2EyxsjCl",
    "outputId": "ed929393-b2f8-4f5f-8db1-2c6cc8b1bcb9"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['bird', 'cat', 'dog']\n"
     ]
    }
   ],
   "source": [
    "animals = [\"bird\", \"cat\", \"dog\"]  # 建立一個有許多動物名稱字串的串列物件\n",
    "print(animals)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 870,
     "status": "ok",
     "timestamp": 1606967119284,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "X3pJQ9sjs1aL",
    "outputId": "c2d44989-ea1f-4b14-83bb-7c2a28ea3add"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hey, there is a bird!\n",
      "Hey, there is a cat!\n",
      "Hey, there is a dog!\n"
     ]
    }
   ],
   "source": [
    "for animal in animals:  # 讀取每個動物的名稱\n",
    "    print(\"Hey, there is a\", animal+\"!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 663,
     "status": "ok",
     "timestamp": 1606967167951,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "Sq2U6wR6tAve",
    "outputId": "00e87d20-43df-41c6-9370-72ae47ad2a47"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n",
      "7\n",
      "8\n",
      "9\n",
      "Boom!\n"
     ]
    }
   ],
   "source": [
    "for number in range(10):  # range 物件也是個序列，也可以依序處理\n",
    "    print(number)\n",
    "\n",
    "print(\"Boom!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "tmBlv7jtkkK8"
   },
   "source": [
    "#### 用 `enumerate()` 搭配串列"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "caMAUdxrvd3B"
   },
   "source": [
    "使用 `enumerate()` 函式，將可以把串列物件轉換為多個 `(索引, 內容)` 的序列物件：\n",
    "\n",
    "> 備註：序列物件裡，裝的是一個一個的 Tuple 物件，是個不可變型態的物件。由於初學比較少使用，被我把介紹的篇幅移到最後去了，在最後會一併介紹。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 1218,
     "status": "ok",
     "timestamp": 1607589191706,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "K6GNregqkuxj",
    "outputId": "dfd500b9-9964-4611-8976-f72b4e9f9e4f"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Bird', 'Cat', 'Dog', 'Eagle']\n"
     ]
    }
   ],
   "source": [
    "animals = [\"Bird\", \"Cat\", \"Dog\", \"Eagle\"]  # 建立一個有許多動物名稱字串的串列物件\n",
    "print(animals)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 1739,
     "status": "ok",
     "timestamp": 1607589192537,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "I0b7_8A5lJxT",
    "outputId": "f0fa2d9c-c2f3-4cd7-bdda-9b80e75b56ad"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The animal Bird has the index 0\n",
      "The animal Cat has the index 1\n",
      "The animal Dog has the index 2\n",
      "The animal Eagle has the index 3\n"
     ]
    }
   ],
   "source": [
    "for key, value in enumerate(animals):  # 透過 enumerate() 函式轉換後\n",
    "                                       # 會產生多個 (索引值, 內容) 的物件，\n",
    "                                       # 所以也需要用兩個物件去承接讀取出來的內容\n",
    "                                       # 在這裡，key 是物件在這個串列中的索引值，value 則為物件內容\n",
    "    print(\"The animal\", value, \"has the index\", key)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 955,
     "status": "ok",
     "timestamp": 1607589192544,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "cA0UPzpFmtzi",
    "outputId": "eea15180-e79c-47bc-ae8a-bb07cef74fac"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Bird', 'Cat', 'Puppy', 'Eagle']\n"
     ]
    }
   ],
   "source": [
    "for index, animal in enumerate(animals):  # 一般為了講究可讀性，讀取出來的物件，會取得有意義些\n",
    "    if animal == \"Dog\":                   # 也可以接著做條件判斷處理，像這裡就是判斷字串內容是否為 Dog\n",
    "        animals[index] = \"Puppy\"          # 若條件成立，把串列裡此索引值的內容從 Dog 改為 Puppy\n",
    "\n",
    "print(animals)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "r3tW2y2BxR6r"
   },
   "source": [
    "> 補充：如果只想要讀取索引值，不需要內容呢？我們可以把讀取出來的內容存成底線 `_`，代表忽略這個物件。\n",
    ">\n",
    "> 像以下這個範例，就是在依序讀取的過程中，判斷當索引值為 1 時，將內容改為空白字串："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 1175,
     "status": "ok",
     "timestamp": 1607589194129,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "NR9nRmEfxkBn",
    "outputId": "5a8e3434-dbbd-4470-f345-ef4b4b714dde"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Bird', '', 'Puppy', 'Eagle']\n"
     ]
    }
   ],
   "source": [
    "for index, _ in enumerate(animals):\n",
    "    if index == 1:\n",
    "        animals[index] = \"\"\n",
    "\n",
    "print(animals)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "3m2blkt7kspO"
   },
   "source": [
    "#### 用 `dict.items()` 搭配字典"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "f0qzZBHwyN4D"
   },
   "source": [
    "類似 `enumerate()` 函式搭配串列的用法，呼叫 `dict.items()` 將可以把字典物件轉換為多個 `(索引, 內容)` 的序列物件："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "id": "UnEOIDs_ydRg"
   },
   "outputs": [],
   "source": [
    "from pprint import pprint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "id": "pBusoF7cmBoK"
   },
   "outputs": [],
   "source": [
    "profile = {\n",
    "    \"name\": \"Vivi\",\n",
    "    \"age\": 18,\n",
    "    \"skills\": [\n",
    "        \"eating\",\n",
    "        \"sleeping\",\n",
    "        \"dreaming\",\n",
    "    ]\n",
    "}\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 817,
     "status": "ok",
     "timestamp": 1607082844708,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "N-kOih8lmXWE",
    "outputId": "16e1051f-9b48-4018-a276-16a5841b2e83"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This is my profile:\n",
      "name = Vivi\n",
      "age = 18\n",
      "skills = ['eating', 'sleeping', 'dreaming']\n"
     ]
    }
   ],
   "source": [
    "print(\"This is my profile:\")\n",
    "\n",
    "for key, value in profile.items():\n",
    "    print(key, \"=\", value)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 1457,
     "status": "ok",
     "timestamp": 1607083083232,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "v7Og2DQlnF0m",
    "outputId": "f3a6aef9-ec2c-45b5-9d09-f46beca8b982"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'name': 'Vivi', 'age': 32, 'skills': ['eating', 'sleeping', 'dreaming']}\n"
     ]
    }
   ],
   "source": [
    "for section, content in profile.items():\n",
    "    if content == 18:\n",
    "        profile[section] = 32\n",
    "\n",
    "print(profile)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "zAiotYTftefS"
   },
   "source": [
    "### `while`：While 迴圈 (While loop)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "UZ11xfPn1TgY"
   },
   "source": [
    "While 迴圈比較簡單：只要 `while` 陳述句後面接的條件為真，就會一直重複執行接下來指定的動作，直到條件不為真時才會停止。\n",
    "\n",
    "既然比較簡單，為什麼會放到 For loop 之後才介紹呢？是因為在我的經驗裡，While 迴圈比較危險：當一個一直為真的條件、搭配一個不會被中斷執行的動作，將會讓這個程式永無止盡的執行⋯⋯。這種情況通常稱作「無窮迴圈」。\n",
    "\n",
    "> 備註：印象中，早些年在執行有無窮迴圈的程式時，真的會把系統的記憶體吃到半點不剩，導致電腦變得超卡頓、甚至直接當機的狀況。現在好像有機會偵測出這個問題並且自動停止執行，但我也沒很想嘗試就是了⋯⋯\n",
    ">\n",
    "> 如果沒有特別的需求，請不要輕易撰寫、或執行無窮迴圈！"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 1196,
     "status": "ok",
     "timestamp": 1607590716518,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "JVx-KG9_vWh2",
    "outputId": "2b6b68ab-5413-47c0-ae69-0535671c8943"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "3\n",
      "6\n",
      "9\n"
     ]
    }
   ],
   "source": [
    "x = 0               # 初始化 x 物件為 0\n",
    "\n",
    "while x < 10:       # 設定在 x < 10 時皆可不斷執行\n",
    "    if x % 3 == 0:  # 判斷 x 除以 3 的餘數為 0 時，才顯示該數字\n",
    "        print(x)\n",
    "    x += 1          # 不會造成無窮迴圈的關鍵：每次執行完時，都記得對 x 做處理\n",
    "                    # 這樣條件才有不為真的一天"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "executionInfo": {
     "elapsed": 1050,
     "status": "ok",
     "timestamp": 1607591116710,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "2ne3IBTsvh7I"
   },
   "outputs": [],
   "source": [
    "# 這就是個無窮迴圈的範例，不要輕易嘗試執行！\n",
    "# \n",
    "# x = 1\n",
    "\n",
    "# while x:  # x 只會一直加 1，條件永遠為真\n",
    "#     print(2**x)\n",
    "#     x += 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "hqO8WT8bBT2L"
   },
   "source": [
    "## 其他流程控制工具"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "RtAlFKy8DQBB"
   },
   "source": [
    "### `break`：中斷迴圈執行"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "cCkB8hfV6NTh"
   },
   "source": [
    "常見的情境是：指定在某條件發生時，中斷迴圈的執行："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 1202,
     "status": "ok",
     "timestamp": 1607591433780,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "4MQI5BfbBn3G",
    "outputId": "0ee99f4e-3234-412d-ff8c-71fe17bdeb18"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "for x in range(1,21):  # 初始化一個 1 - 20 的數列，並依序針對數列中的數字進行處理\n",
    "    if x % 4 == 0:     # 判斷 x 是否為 4 的倍數\n",
    "        break          # 條件為真時，中斷迴圈執行\n",
    "    print(x)           # 條件不成立時，顯示該數字"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "hUIWLfVhDLqm"
   },
   "source": [
    "### `continue`：不執行 `continue` 陳述句底下的動作，直接進行下一輪迴圈"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ABItnGQN6t_U"
   },
   "source": [
    "常見的情境是：指定在某條件發生時，不做任何處理，並返回「迴圈程式碼的第一行」再次執行迴圈："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 797,
     "status": "ok",
     "timestamp": 1606973366901,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "c014z0B8EMd7",
    "outputId": "f565d773-ae62-4cd4-dc84-11f7d907e18d"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "5\n",
      "6\n",
      "7\n",
      "9\n",
      "10\n",
      "11\n",
      "13\n",
      "14\n",
      "15\n",
      "17\n",
      "18\n",
      "19\n"
     ]
    }
   ],
   "source": [
    "for x in range(1,21):\n",
    "    if x % 4 == 0:\n",
    "        continue\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Auz-uRYD7p8b"
   },
   "source": [
    "為什麼強調要回到「迴圈程式碼的第一行」再次執行呢？因為裡面是有玄機的：以上面的例子來看，當執行過第一行之後，`range` 物件裡就會將以經處理過的數字給移除，所以在遇見 `continue` 陳述式時，回到第一行依然可以繼續將剩下的數字給處理完。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 802,
     "status": "ok",
     "timestamp": 1607663996188,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "uSiRBGj59Mm5",
    "outputId": "f4eff7fa-cb59-469d-8d94-85d674906439"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "[2, 3, 4, 5, 6, 7, 8, 9]\n"
     ]
    }
   ],
   "source": [
    "# 讓我們用些方法來檢查 range 物件執行的邏輯\n",
    "list(range(10))\n",
    "range_iter = iter(range(10))\n",
    "print(next(range_iter))\n",
    "print(next(range_iter))\n",
    "print(list(range_iter))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Z7_y3rZ4Pmnh"
   },
   "source": [
    "再看以下的例子：這樣會導致無窮迴圈的出現"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "id": "XkMrnF4xEV5i"
   },
   "outputs": [],
   "source": [
    "# 以下的執行過程為無窮迴圈，非必要請不易執行！\n",
    "# \n",
    "# x = 1\n",
    "# \n",
    "# while x < 21:\n",
    "#     if x % 4 == 0:\n",
    "#         continue\n",
    "#     print(x)\n",
    "#     x += 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "FGWGeziIP5Fl"
   },
   "source": [
    "所以，在操作 While 迴圈時，如何設定一個會終止的條件就變得相當重要。上面的例子，可以改成底下的形式來避免形成無窮迴圈："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 820,
     "status": "ok",
     "timestamp": 1607664167834,
     "user": {
      "displayName": "黃種平",
      "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GjCoYcYDAMAK-J-MvClxwWJY0fvKYsny6BL962ZNA=s64",
      "userId": "12486487678081777487"
     },
     "user_tz": -480
    },
    "id": "lWDRNtPPEXfB",
    "outputId": "b7504043-69a3-4268-b9e9-75a72f5e6097"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "5\n",
      "6\n",
      "7\n",
      "9\n",
      "10\n",
      "11\n",
      "13\n",
      "14\n",
      "15\n",
      "17\n",
      "18\n",
      "19\n"
     ]
    }
   ],
   "source": [
    "x = 1\n",
    "\n",
    "while x < 21:\n",
    "    if x % 4 == 0:\n",
    "        x += 1\n",
    "        continue\n",
    "    print(x)\n",
    "    x += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "gSWULreaGgg5"
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "colab": {
   "authorship_tag": "ABX9TyPUmsJvArELzzoRWtWEFXQz",
   "name": "Python Basics - Chapter 5 - Control flows and Iterables.ipynb",
   "provenance": [],
   "toc_visible": true
  },
  "jupytext": {
   "formats": "ipynb,py:light"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
